from DrissionPage import Chromium
from DrissionPage.common import Settings
from enum import Enum
import time
import re
import traceback

Settings.set_language('zh_cn')  # 设置为中文
file_path = "/Users/liugan/workspace/crawler/data\花粉俱乐部.txt"
# 检索关键词
keywords = ["动画", "动效"]
# 启动或接管浏览器，并创建标签页对象
tab = Chromium().latest_tab
# 这之后出现的弹窗都会自动确认
tab.browser.set.auto_handle_alert()
# 跳转到花粉俱乐部
tab.get('https://cn.club.vmall.com/mhw/consumer/cn/community/mhwnews/allcirclehome/')

#帖子详情：视频
# tab.get('https://cn.club.vmall.com/mhw/consumer/cn/community/mhwnews/video/id_1000000000002498601/action_comment/')
# 帖子详情：非视频
# tab.get('https://cn.club.vmall.com/mhw/consumer/cn/community/mhwnews/question/id_1000000000002500898/')

# HarmonyOS NEXT:帖子详情：非视频
# tab.get('https://cn.club.vmall.com/mhw/consumer/cn/community/mhwnews/dynamic/id_1000000000002494584')
# HarmonyOS NEXT:帖子详情：视频
# tab.get('https://cn.club.vmall.com/mhw/consumer/cn/community/mhwnews/video/id_1000000000002491676')

# 有视频，但是详情页非通常视频样式，而是非视频样式
# tab.get('https://cn.club.vmall.com/mhw/consumer/cn/community/mhwnews/question/id_1000000000002502206/')

def is_ele_visible(ele):
    style = ele.attr('style')
    if style is not None and re.search(r"display: ?none", style, flags=re.IGNORECASE):
        return False
    return ele.states.is_displayed

# 找到对应的模块
def find_module_by_name(module_container, module_name):
    modules = module_container.children()
    for module in modules:
        text = module.ele("@tag()=div").text
        if text == module_name:
            return module
    return None

def ele_scroll_to_see(ele):
    ele.wait.has_rect()
    ele.scroll.to_see()

def click_ele(ele):
    ele.wait.has_rect()
    ele.click()

def wait_ele_displayed(tab, locator):
    tab.wait.ele_displayed(locator, timeout = 3)
    return tab.ele(locator)

def expand_more_until_tail(parent, locator, more_text):
    while True:
        more_comment_ele = parent.ele(locator)
        if not more_comment_ele:
            print(f'======>>>>>没找到：{more_text}')
        else:
            if not is_ele_visible(more_comment_ele):
                print(f'======>>>>>不可见：{more_text}')
            if not re.search(rf"{more_text}", more_comment_ele.text, flags=re.IGNORECASE):
                print(f'======>>>>>内容不是：{more_text}')
        if not more_comment_ele or not is_ele_visible(more_comment_ele) or not re.search(rf"{more_text}", more_comment_ele.text, flags=re.IGNORECASE):
            print("=====>>>>>expand_more_until_tail：no-more-break")
            break
        try:
            ele_scroll_to_see(more_comment_ele)
            click_ele(more_comment_ele)
            print("=====>>>>>expand_more_until_tail:ckick")
        except Exception:
            print("=====>>>>>expand_more_until_tail:error")
            break

def expand_reply_more_until_tail(reply_comment_list_ele, more_text):
    while True:
        children = reply_comment_list_ele.children()
        more_comment_ele = children[len(children) - 1]
        if not is_ele_visible(more_comment_ele):
            print(f'======>>>>>不可见：{more_text}')
        if not re.search(rf"{more_text}", more_comment_ele.text, flags=re.IGNORECASE):
            print(f'======>>>>>内容不是：{more_text}')
        if not is_ele_visible(more_comment_ele) or not re.search(rf"{more_text}", more_comment_ele.text, flags=re.IGNORECASE):
            print("=====>>>>>expand_reply_more_until_tail-more-break")
            break
        try:
            ele_scroll_to_see(more_comment_ele)
            click_ele(more_comment_ele)
            print("=====>>>>>expand_reply_more_until_tail:ckick")
        except Exception:
            print("=====>>>>>expand_reply_more_until_tail:error")
            break

def process_not_video_card_deail(tab, card_desc):
    print("处理非视频卡：")
    print(card_desc)
    print('\n')
    comment_container = wait_ele_displayed(tab, '@class:common-list-wrap')
    if not comment_container:
        return False
    # 如果有更多评论，则全部展开
    expand_more_until_tail(comment_container, '@@class=more-common cursor-pointer', '查看更多评论')

    comment_list = comment_container.eles('@tag()=li')
    with open(file_path, 'a', encoding='utf-8') as f:
        f.writelines(card_desc)
        f.write('\n')
    if not comment_list:
        print("没有评论.....\n")
        with open(file_path, 'a', encoding='utf-8') as f:
            f.write('\n\n\n')
        return True
    for comment_item in comment_list:
        comment_content = comment_item.children()[1]
        more_comments = comment_content.children()[1]
        print('----------------------评论内容：-----------------------')
        print(comment_item.texts())
        print('更多按钮的stayle:')
        print(more_comments.attr('style')) # display: none;
        print('\n')
        with open(file_path, 'a', encoding='utf-8') as f:
            f.write('----------------------评论内容：-----------------------\n')
            f.writelines(comment_item.texts())
            f.write("\n")
        # 如果有更多评论，则需要展开更多评论，然后记录
        if is_ele_visible(more_comments):
            print("还有更多评论，点击展开...\n")
            more_comments.click()
            comment_dialog = wait_ele_displayed(tab, '@class=ui-dialog-v5 ui-dialog-v5-cont')
            if comment_dialog and is_ele_visible(comment_dialog):
                reply_comment_list_ele = comment_dialog.ele('@class=sub-comment-wrap')
                # 如果有更多评论回复，则全部展开
                expand_reply_more_until_tail(reply_comment_list_ele, '查看更多评论')
                with open(file_path, 'a', encoding='utf-8') as f:
                    f.writelines(reply_comment_list_ele.texts())
                    f.write("\n")
                print('----------------------更多评论内容：-----------------------')
                print(reply_comment_list_ele.texts())
                comment_dialog.ele('@class=ui-dialog-close').click()
                continue
        # 如果没有更多评论，只记录这一条评论
        print("没有更多评论，不需要展开...\n")
    with open(file_path, 'a', encoding='utf-8') as f:
        f.write('\n\n\n')
    return True

def process_video_card_detail(tab, card_desc):
    print("处理视频卡... \n")
    print(card_desc)
    print('\n')
    icon_list_ele = wait_ele_displayed(tab, '@class=comment-icon-wrap vertical')
    # 点击拉出评论列表
    if icon_list_ele:
        icon_list_ele.children()[1].click()
    else:
        return False
    comment_container = wait_ele_displayed(tab, '@class:common-list-wrap')
    # 如果有更多评论，则全部展开
    expand_more_until_tail(comment_container, '@@class=more-common cursor-pointer', '查看更多评论')

    comment_list = comment_container.eles('@tag()=li')
    with open(file_path, 'a', encoding='utf-8') as f:
        f.writelines(card_desc)
        f.write('\n')
    if not comment_list:
        print("没有评论.....\n")
        with open(file_path, 'a', encoding='utf-8') as f:
            f.write('\n\n\n')
        return True
    for comment_item in comment_list:
        ele_scroll_to_see(comment_item)
        comment_content = comment_item.children()[1]
        more_comments = comment_content.children()[1]
        print('----------------------评论内容：-----------------------')
        print(comment_item.texts())
        print('更多按钮的stayle:')
        print(more_comments.attr('style')) # display: none;
        print('\n')
        with open(file_path, 'a', encoding='utf-8') as f:
            f.write('----------------------评论内容：-----------------------\n')
            f.writelines(comment_item.texts())
            f.write("\n")
        # 如果有更多评论，则需要展开更多评论，然后记录
        if is_ele_visible(more_comments):
            print("还有更多评论，点击展开...\n")
            more_comments.click()
            comment_dialog = wait_ele_displayed(tab, '@class=comment-detail')
            if comment_dialog and is_ele_visible(comment_dialog):
                reply_comment_list_ele = comment_dialog.ele('@class=sub-comment-wrap')
                # 如果有更多评论回复，则全部展开
                expand_reply_more_until_tail(reply_comment_list_ele, '查看更多评论')
                with open(file_path, 'a', encoding='utf-8') as f:
                    f.writelines(reply_comment_list_ele.texts())
                    f.write("\n")
                print('----------------------更多评论内容：-----------------------')
                print(reply_comment_list_ele.texts())
                comment_dialog.ele('@class=img-box').click()
                continue
        # 如果没有更多评论，只记录这一条评论
        print("没有更多评论，不需要展开...\n")
    with open(file_path, 'a', encoding='utf-8') as f:
        f.write('\n\n\n')
    return True

def process_card_deail(is_comment_empty, is_not_video, card_desc):
    detail_title = wait_ele_displayed(tab, '@@class=nav-title@@text()=帖子详情')
    try:
        if not any(keyword in card_desc for keyword in keywords):
            print('不包含检索关键词，跳过...\n')
            return
        if not detail_title:
            print("不在帖子详情页... \n")
            if wait_ele_displayed(tab, '@@class=nav-title@@text()=个人主页'):
                print('意外跳转到个人主页，直接返回... \n')
            return
        # 非视频卡
        if is_not_video:
            # # 左侧内容区
            # left_content = wait_ele_displayed(tab, '@class=left-cont')
            # #右侧评论区
            # right_content = wait_ele_displayed(tab, '@class=right-cont')
            processed = process_not_video_card_deail(tab, card_desc)
            if not processed:
                process_video_card_detail(tab, card_desc)
        else:
            # video_card_detail = wait_ele_displayed(tab, '@@tag()=video@@class=in-video')
            processed = process_video_card_detail(tab, card_desc)
            if not processed:
                process_not_video_card_deail(tab, card_desc)
    finally:
        if detail_title:
            time.sleep(1)
            tab.ele('@class=nav-back').click()

# 返回是否是最后一张卡
def process_card(card_container, card_position, container_name):
    try:
        try_count = 1
        while True:
            card = card_container.ele('xpath:./div[position()=' + str(card_position) +']')
            if not card:
                if try_count <= 3:
                    print('未找到卡片：' + str(card_position) + '，尝试滚动浏览器到底部，尝试次数：' + str(try_count) + '\n')
                    wait_ele_displayed(tab, '@tag()=html').scroll.to_bottom()
                    try_count = try_count + 1
                    time.sleep(1)
                    continue
                else:
                    return True # 走到此处可以认为已经是最后一张卡
            print(container_name + '-处理第：' + str(card_position) + '张卡片')
            try_count = 1
            card_comment_icon = card.ele('@class=state-item cursor-pointer')
            ele_scroll_to_see(card_comment_icon)
            tab.listen.start('https://sgw-cn.c.huawei.com/forward/club/content_h5/queryThreadDetail')
            card_comment_icon.click()
            body = tab.listen.wait(timeout = 10).response.body # 等待并获取一个数据包
            card_desc = '未获取到内容描述'
            if not body or not body['data']:
                is_comment_empty =  True
                is_not_video = True
                print('======>>>未获取到响应数据body:')
                print(body)
                print('\n')
            else:
                is_comment_empty = not body['data']['postList']
                is_not_video = not body['data']['video']
                content = body['data']['content']
                if content:
                    card_desc = content
            process_card_deail(is_comment_empty, is_not_video, card_desc)
            return False
    except Exception:
        traceback.print_exc()
        return False

def process_module_item(module_item):
    module_item.click()

    skiped_card_containers = []
    card_container_positon = 0
    card_position = 1
    while True:
        card_root = wait_ele_displayed(tab, '@id=vueWaterfall')
        card_container_list = card_root.eles('xpath:./div[contains(@class, "column-cont")]')
        # 已经结束的容器不需要删除，只需要跳过就行          
        is_last_card = process_card(card_container_list[card_container_positon], card_position, '容器' + str(card_container_positon))
        if is_last_card:
            skiped_card_containers.append(card_container_positon)
        if card_container_positon >= len(card_container_list) - 1:
            card_container_positon = 0
            # 每个容器都走一轮之后卡片索引才能+1
            card_position = card_position + 1
        else:
            card_container_positon = card_container_positon + 1

    # while len(card_container_list) > 0:
    #     remove_list = []
    #     for index in range(len(card_container_list)):
    #         is_last_card = process_card(card_container_list[index], card_position, '容器' + str(index))
    #         time.sleep(1)
    #         if is_last_card:
    #             remove_list.append(index)
    #     for index in sorted(remove_list, reverse=True):
    #         del card_container_list[index]
    #     card_position = card_position + 1

# 找到分类内容父容器
module_container = wait_ele_displayed(tab, '@@tag()=div@@class=circle-index-card')
module = find_module_by_name(module_container, "推荐")
if module is not None:
    module.scroll.to_see()
    module_item_list = module.children()[1:]
    process_module_item(module_item_list[1])

# process_card_deail(False, False, "测试标题")
# process_not_video_card_deail(tab, "测试测试")